//
//  TestUtils.swift
//  CloudKitCodableTests
//
//  Created by Guilherme Rambo on 12/05/18.
//  Copyright © 2018 Guilherme Rambo. All rights reserved.
//

import XCTest
import CloudKit
@testable import CloudKitCodable

private final class _TestBundleClass {}

extension Bundle {
    static var testBundle: Bundle {
        return Bundle(for: _TestBundleClass.self)
    }
}

extension CKRecord {
    /// Creates a temporary record to simulate what would happen when encoding a CKRecord
    /// from a value that was previosly encoded to a CKRecord and had its system fields set
    static var systemFieldsDataForTesting: Data {
        let zoneID = CKRecordZoneID(zoneName: "ZoneABCD", ownerName: "OwnerABCD")
        let recordID = CKRecordID(recordName: "RecordABCD", zoneID: zoneID)
        let testRecord = CKRecord(recordType: "Person", recordID: recordID)
        let data = NSMutableData()
        let coder = NSKeyedArchiver.init(forWritingWith: data)
        coder.requiresSecureCoding = true
        testRecord.encodeSystemFields(with: coder)
        coder.finishEncoding()

        return data as Data
    }

    static var testRecord: CKRecord {
        guard let url = Bundle.testBundle.url(forResource: "Rambo", withExtension: "ckrecord") else {
            fatalError("Required test asset Rambo.ckrecord not found")
        }

        return NSKeyedUnarchiver.unarchiveObject(withFile: url.path) as! CKRecord
    }
}

/// Validates that all fields in `record` match the expectations of encoding the test `Person` struct to a `CKRecord`
///
/// - Parameter record: A record generated by encoding `Person.rambo` with `CloudKitRecordEncoder`
func _validateRamboFields(in record: CKRecord) {
    XCTAssertEqual(record.recordType, "Person")
    XCTAssertEqual(record["name"] as? String, "Guilherme Rambo")
    XCTAssertEqual(record["age"] as? Int, 26)
    XCTAssertEqual(record["website"] as? String, "https://guilhermerambo.me")
    XCTAssertEqual(record["isDeveloper"] as? Bool, true)

    guard let asset = record["avatar"] as? CKAsset else {
        XCTFail("URL property with a file URL should encode to a CKAsset")
        return
    }

    XCTAssertEqual(asset.fileURL.path, "/Users/inside/Library/Containers/br.com.guilhermerambo.CloudKitRoundTrip/Data/Library/Caches/CloudKit/aa007d03cf247aebef55372fa57c05d0dc3d8682/Assets/7644AD10-A5A5-4191-B4FF-EF412CC08A52.01ec4e7f3a4fe140bcc758ae2c4a30c7bbb04de8db")
    
    XCTAssertNil(record[_CKSystemFieldsKeyName], "\(_CKSystemFieldsKeyName) should NOT be encoded to the record directly")
}

extension Person {

    /// Sample person for tests
    static let rambo = Person(
        cloudKitSystemFields: nil,
        name: "Guilherme Rambo",
        age: 26,
        website: URL(string:"https://guilhermerambo.me")!,
        avatar: URL(fileURLWithPath: "/Users/inside/Library/Containers/br.com.guilhermerambo.CloudKitRoundTrip/Data/Library/Caches/CloudKit/aa007d03cf247aebef55372fa57c05d0dc3d8682/Assets/7644AD10-A5A5-4191-B4FF-EF412CC08A52.01ec4e7f3a4fe140bcc758ae2c4a30c7bbb04de8db"),
        isDeveloper: true
    )

}

extension PersonWithCustomIdentifier {

    static let rambo = PersonWithCustomIdentifier(cloudKitSystemFields: nil,
                                                  cloudKitIdentifier: "MY-ID",
                                                  name: "Guilherme Rambo")
}
